package com.apimanage.auth.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.apimanage.common.exception.ApiException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.apimanage.auth.model.dto.UserInfoDTO;
import com.apimanage.auth.service.AuthInternalService;
import com.apimanage.common.dto.AuthDTO;
import com.apimanage.common.dto.UserDTO;
import com.apimanage.common.utils.JwtTokenUtil;
import com.apimanage.common.entity.Result;
import com.apimanage.common.response.ResultCode;
import com.apimanage.common.service.AuthService;
import com.apimanage.common.service.UserCenterService;
import org.apache.dubbo.config.annotation.DubboReference;

/**
 * 认证控制器 - 基于Spring Security+JWT实现
 * 处理用户登录、注册、获取用户信息等认证授权相关请求
 * 作为系统安全的第一道防线，负责身份验证和会话管理
 * 
 * @author API管理平台
 * @version 1.0
 * @since 2023-01-01
 */
@RestController
@RequestMapping("/auth")
public class AuthController {

    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private AuthInternalService authInternalService;
    
    @DubboReference(timeout = 3000)
    private AuthService authService;
    
    // 设置check=false，避免因为user-center服务不可用而导致auth-center启动失败
    @DubboReference(check = false, timeout = 3000)
    private UserCenterService userService;

    @Autowired
    private AuthenticationManager authenticationManager;

    // 使用静态方法调用统一的JWT工具类，无需注入

    /**
     * 用户登录接口
     * 接收用户名和密码，通过Spring Security进行身份验证，成功后生成JWT令牌
     * 
     * @param loginRequest 包含用户名(username)和密码(password)的请求体
     * @return 登录结果，包含JWT令牌、用户名和角色信息
     * @throws BadCredentialsException 当用户名或密码错误时抛出
     * @throws UsernameNotFoundException 当用户不存在时抛出
     */
    @PostMapping("/login")
    public Result login(@RequestBody Map<String, String> loginRequest) {
        String username = loginRequest.get("username");
        String password = loginRequest.get("password");

        logger.info("接收到登录请求: username = {}", username);

        try {
            // 记录详细的登录请求信息
            logger.debug("登录请求详细信息: username={}, passwordProvided={}", 
                         username, password != null ? "已提供" : "未提供");
            
            // 使用Spring Security的认证管理器进行认证
            logger.debug("开始Spring Security认证流程");
            UsernamePasswordAuthenticationToken authenticationToken = 
                new UsernamePasswordAuthenticationToken(username, password);
            logger.debug("创建认证令牌对象: principal={}, credentials={}", 
                         authenticationToken.getPrincipal(), 
                         authenticationToken.getCredentials() != null ? "已设置" : "未设置");
            Authentication authentication = authenticationManager.authenticate(authenticationToken);
            logger.debug("Spring Security认证成功: principal类型={}", 
                         authentication.getPrincipal().getClass().getName());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            logger.debug("已将认证信息设置到SecurityContext");
            
            // 认证成功后，从认证信息中获取用户详情
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            logger.debug("获取到用户详情: username={}, authoritiesSize={}", 
                         userDetails.getUsername(), userDetails.getAuthorities().size());
            
            // 创建用户DTO对象
            UserDTO userDTO = new UserDTO();
            userDTO.setUsername(userDetails.getUsername());
            
            // 从用户详情中提取角色信息
            logger.debug("开始提取用户角色信息");
            List<String> roles = userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .filter(authority -> authority.startsWith("ROLE_"))
                .map(role -> role.substring(5)) // 去掉"ROLE_"前缀
                .collect(Collectors.toList());
            userDTO.setRoles(roles);
            logger.debug("提取到用户角色: {}", roles);
            
            // 通过UserCenterService获取完整用户信息（包括ID）
            logger.debug("开始调用UserCenterService获取完整用户信息");
            try {
                UserDTO fullUserDTO = userService.getUserByUsername(username);
                logger.debug("UserCenterService调用结果: fullUserDTO={}", 
                             fullUserDTO != null ? "存在" : "不存在");
                if (fullUserDTO != null && fullUserDTO.getId() != null) {
                    userDTO.setId(fullUserDTO.getId());
                    logger.info("成功获取用户ID: {}", userDTO.getId());
                } else {
                    logger.warn("未能获取到用户ID信息");
                }
            } catch (Exception e) {
                logger.warn("获取用户ID时出错: {}, 异常类型: {}", 
                           e.getMessage(), e.getClass().getName());
                e.printStackTrace();
            }
            
            // 生成JWT令牌
            logger.debug("开始生成JWT令牌，用户DTO信息: username={}, id={}, roles={}", 
                         userDTO.getUsername(), userDTO.getId(), userDTO.getRoles());
            String token = JwtTokenUtil.generateToken(userDTO);
            logger.debug("JWT令牌生成成功，令牌长度: {}", token != null ? token.length() : 0);
            
            // 构建返回结果
            logger.debug("开始构建返回结果");
            Map<String, Object> result = new HashMap<>();
            result.put("token", token);
            result.put("username", username);
            result.put("roles", roles);
            logger.debug("返回结果构建完成: 包含token={}, username={}, roles={}", 
                         token != null ? "是" : "否", username, roles);

            logger.info("登录成功: username = {}", username);
            return Result.success(result);
        } catch (BadCredentialsException e) {
            logger.error("登录失败: 用户名或密码错误, username = {}, 异常信息: {}", username, e.getMessage());
            e.printStackTrace();
            return Result.error(ResultCode.USERNAME_OR_PASSWORD_ERROR, "用户名或密码错误");
        } catch (UsernameNotFoundException e) {
            logger.error("登录失败: 用户不存在, username = {}, 异常信息: {}", username, e.getMessage());
            e.printStackTrace();
            return Result.error(ResultCode.USERNAME_OR_PASSWORD_ERROR, "用户名或密码错误");
        } catch (Exception e) {
            logger.error("登录失败: username = {}, 错误类型: {}, 错误信息: {}", 
                        username, e.getClass().getName(), e.getMessage());
            e.printStackTrace();
            return Result.error(ResultCode.FAIL, "登录失败，请稍后重试");
        }
    }

    /**
     * 用户注册接口
     * 接收用户注册信息，通过AuthService进行用户创建和密码加密
     * 
     * @param authDTO 包含用户名、密码、邮箱等注册信息的数据传输对象
     * @return 注册结果，包含新创建的用户信息
     * @throws ApiException 当注册信息不符合要求时抛出
     */
    @PostMapping("/register")
    public Result register(@RequestBody AuthDTO authDTO) {
        try {
            // 使用AuthService进行注册
            Map<String, Object> result = authService.register(authDTO);
            return Result.success(result);
        } catch (Exception e) {
            // 记录详细日志供调试使用
            logger.error("注册失败: username = {}, 错误信息: {}", authDTO.getUsername(), e.getMessage(), e);

            // 根据异常类型返回不同的错误信息
            if (e instanceof ApiException) {
                return Result.error(ResultCode.FAIL, e.getMessage());
            } else {
                // 对于系统级异常，返回通用错误信息，避免暴露内部细节
                return Result.error(ResultCode.FAIL, "注册失败，请稍后重试");
            }
        }
    }

    /**
     * 获取当前用户信息
     * 从Authorization头中提取JWT令牌，验证其有效性后获取用户详细信息
     * 该接口需要USER角色权限才能访问
     * 
     * @param authorizationHeader 包含JWT令牌的Authorization请求头，格式为"Bearer {token}"
     * @return 用户信息，包含用户名、邮箱、电话和角色等
     */
    @GetMapping("/getCurrentUserInfo")
    @PreAuthorize("hasRole('USER')")  // 要求具有 USER 角色
    public Result getCurrentUserInfo(@RequestHeader("Authorization") String authorizationHeader) {
        try {
            // 从Authorization头中提取token，通常格式为"Bearer {token}"
            String token = null;
            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                token = authorizationHeader.substring(7);
            }

            // 验证token是否存在
            if (token == null || token.isEmpty()) {
                return Result.error(ResultCode.UNAUTHORIZED, "token不能为空");
            }

            // 验证token有效性
            if (!JwtTokenUtil.validateToken(token)) {
                return Result.error(ResultCode.UNAUTHORIZED, "token已过期或无效");
            }

            UserInfoDTO userInfoDTO = authInternalService.getUserInfoByToken(token);
            if (userInfoDTO != null) {
                return Result.success(userInfoDTO);
            }
            return Result.error(ResultCode.UNAUTHORIZED, "未授权或token无效");
        } catch (Exception e) {
            logger.error("获取用户信息失败: {}", e.getMessage(), e);
            return Result.error(ResultCode.FAIL, "获取用户信息失败: " + e.getMessage());
        }
    }

    /**
     * 用户登出接口
     */
    @PostMapping("/logout")
    public Result logout() {
        // 清除认证上下文
        SecurityContextHolder.clearContext();
        return Result.success("登出成功");
    }

}